﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using HtmlToImage;
using System.Drawing.Drawing2D;
using System.IO;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace ClippingEditor
{
	public partial class Dlg_ImageEditor : Form
	{

		private Bitmap _oriImage;
		private Bitmap _undoImage;
		string oriStr = "原始大小";
		string autoStr = "自适应";
		bool isbusy = false;
		public bool Makeselection = false;
		public bool MoveSelection = false;
		public bool MoveSelectionEdge = false;

		public Edge draggingEdge;

		private SelectionInfo _currentSelectionArea = new SelectionInfo();


		int moveStartX;
		int moveStartY;


		public Pen cropPen;
		private double[] _ratios = new double[7];

		private Timer _scrollTimer;
		private Timer _infoTimer;
		private int _infoShowCount = 0;
		Point _currentMousePosition;
		Point _mouseDownPosition;
		bool _doubleClick = false;
		private Action<Bitmap> _addPic;
		bool _isEditing = false;
		#region 构造函数

		public Dlg_ImageEditor()
		{
			InitializeComponent();
			cropPen = new Pen(Color.Red, 1);
			cropPen.DashStyle = DashStyle.Solid;
			initRatios();
			this.MouseWheel += new MouseEventHandler(Panel1_MouseWheel);
			initScrollTimer();
			initInfoTimer();
			this.btn_Select.Checked = true;
		}



		public Dlg_ImageEditor(string url, Action<Bitmap> addPicAction)
			: this()
		{
			this.txt_URL.Text = url;

			if (!string.IsNullOrEmpty(url))
				btn_ConvertToImage_Click(null, null);
			this._addPic = addPicAction;
		}
		public Dlg_ImageEditor(Bitmap img, Action<Bitmap> addPicAction)
			: this()
		{
			this._isEditing = true;
			this.toolStrip1.Visible = false;
			this._oriImage = img;
			this.pictureBox1.Image = img;
			this._addPic = addPicAction;
			setImgSizeLabel();
			changeToOriSize();
		}
		#endregion


		private void initScrollTimer()
		{
			_scrollTimer = new Timer();
			_scrollTimer.Interval = 400;
			_scrollTimer.Tick += new EventHandler(_scrollTimer_Tick);
		}
		private void initInfoTimer()
		{
			_infoTimer = new Timer();
			_infoTimer.Interval = 600;
			_infoTimer.Tick += new EventHandler(_infoTimer_Tick);

		}

		void _infoTimer_Tick(object sender, EventArgs e)
		{
			_infoShowCount += 1;
			this.toolStripLabel_Info.Visible = !this.toolStripLabel_Info.Visible;
			if (_infoShowCount >= 6)
			{
				_infoTimer.Stop();
				this.toolStripLabel_Info.Visible = false;
			}
		}
		void _scrollTimer_Tick(object sender, EventArgs e)
		{
			var currentPosition = this.splitContainer1.Panel1.AutoScrollPosition;
			if (_currentMousePosition.Y + currentPosition.Y > this.splitContainer1.Panel1.Height)
			{

				int y = currentPosition.Y - 120;
				if (y > 0)
					y = 0;
				Point newPosition = new Point(Math.Abs(currentPosition.X), Math.Abs(y));
				this.splitContainer1.Panel1.AutoScrollPosition = newPosition;
			}
		}




		/// <summary>
		/// 初始化缩放比例
		/// </summary>
		private void initRatios()
		{
			for (int i = 0; i < 4; i++)
			{
				double mi1 = Math.Pow(2, (double)(0 - i));
				double mi2 = Math.Pow(2, (double)(0 + i));
				_ratios[3 - i] = mi1;
				_ratios[3 + i] = mi2;
			}
		}

		/// <summary>
		/// 鼠标滚轮控制滚动条
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void Panel1_MouseWheel(object sender, MouseEventArgs e)
		{
			var currentPosition = this.splitContainer1.Panel1.AutoScrollPosition;
			int y = currentPosition.Y + e.Delta;
			if (y > 0)
				y = 0;
			Point newPosition = new Point(Math.Abs(currentPosition.X), Math.Abs(y));
			this.splitContainer1.Panel1.AutoScrollPosition = newPosition;

		}


		/// <summary>
		/// 开始截图
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_ConvertToImage_Click(object sender, EventArgs e)
		{
			this.isbusy = true;
			this.Cursor = Cursors.WaitCursor;
			//HtmlCapture hc = new HtmlCapture(this.webBrowser1);
			clearSelectionInfo();
			HtmlCapture hc = new HtmlCapture();
			hc.HtmlImageCapture +=
			   new HtmlCapture.HtmlCaptureEvent(ImageCaptured);
			try
			{
				hc.Create(txt_URL.Text);
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
		}

		/// <summary>
		/// 地址栏按回车键，开始截图
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void txt_URL_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == 13)
			{
				if (!string.IsNullOrEmpty(txt_URL.Text))
					btn_ConvertToImage_Click(null, null);

			}
		}


		/// <summary>
		/// 截图完成
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="url"></param>
		/// <param name="image"></param>
		/// <param name="html"></param>
		void ImageCaptured(object sender, Uri url, Bitmap image, string html)
		{
			this._oriImage = image;
			pictureBox1.Image = image;
			setImgSizeLabel();
			changeToOriSize();
			this.isbusy = false;

			var multiPage = getMultiPageUrls(url, html);
			if (multiPage != null && multiPage.Count > 0)
				showMultiPageLinks(multiPage, url, image);
			else
				clearMultiPageLinks();
			this.Cursor = Cursors.Default;
		}
		private void showMultiPageLinks(Dictionary<int, string> pageUrls, Uri currentPage, Bitmap currentImg)
		{
			this.flowLayoutPanel_MultiPageLinks.Controls.Clear();
			LinkLabel ll0 = new LinkLabel();
			ll0.Text = "初始页";
			ll0.Click += new EventHandler(ll_Click);
			ll0.Tag = currentImg;
			ll0.Width = 40;
			ll0.Enabled = false;
			this.flowLayoutPanel_MultiPageLinks.Controls.Add(ll0);
			foreach (var kv in pageUrls)
			{
				LinkLabel ll = new LinkLabel();
				ll.Text = string.Format("[{0}]", kv.Key);
				ll.Click += new EventHandler(ll_Click);
				ll.Tag = kv.Value;

				ll.Enabled = false;
				if (kv.Key < 10)
					ll.Width = 35;
				else
					ll.Width = 45;
				this.flowLayoutPanel_MultiPageLinks.Controls.Add(ll);
				HtmlCapture hc = new HtmlCapture();
				hc.HtmlImageCapture +=
				   new HtmlCapture.HtmlCaptureEvent(ImageCaptured2);
				try
				{
					hc.Create(kv.Value);
				}
				catch (Exception ex)
				{
					MessageBox.Show(ex.Message);
				}
			}
			if (pageUrls.Count > 0)
				this.checkBox_LockSelectionArea.Visible = true;
		}
		void ImageCaptured2(object sender, Uri url, Bitmap image, string html)
		{
			foreach (Control c in this.flowLayoutPanel_MultiPageLinks.Controls)
			{
				LinkLabel ll = c as LinkLabel;
				if (ll != null)
				{
					if ((ll.Tag as string) == url.OriginalString)
					{
						ll.Tag = image;
						ll.Enabled = true;
						break;
					}
				}
			}
		}
		void ll_Click(object sender, EventArgs e)
		{
			LinkLabel ll = sender as LinkLabel;
			if (ll == null)
				return;
			foreach (LinkLabel l in this.flowLayoutPanel_MultiPageLinks.Controls)
			{
				l.Enabled = true;
			}
			ll.Enabled = false;
			Bitmap image = ll.Tag as Bitmap;
			this._oriImage = image;

			if (!checkBox_LockSelectionArea.Checked)
			{
				clearSelectionInfo();
				pictureBox1.Image = image;
			}
			else
			{
				Bitmap picWithRectSelectiong = new Bitmap(this._oriImage);
				Graphics g = Graphics.FromImage(picWithRectSelectiong);

				g.DrawRectangle(cropPen, _currentSelectionArea.cropX_Image, _currentSelectionArea.cropY_Image, _currentSelectionArea.cropWidth_Image, _currentSelectionArea.cropHeight_Image);
				SolidBrush b = new SolidBrush(Color.FromArgb(100, 200, 200, 200));
				g.FillRectangle(b, _currentSelectionArea.cropX_Image, _currentSelectionArea.cropY_Image, _currentSelectionArea.cropWidth_Image, _currentSelectionArea.cropHeight_Image);

				pictureBox1.Image = picWithRectSelectiong;

			}

			setImgSizeLabel();
			changeToOriSize();
			this.Cursor = Cursors.Default;
		}
		private void clearMultiPageLinks()
		{
			this.flowLayoutPanel_MultiPageLinks.Controls.Clear();
			this.checkBox_LockSelectionArea.Visible = false;
		}
		private Dictionary<int, string> getMultiPageUrls(Uri currentUrl, string html)
		{
			Dictionary<int, string> rtn = new Dictionary<int, string>();

			foreach (Match m in Regex.Matches(html, "<A[^>]*?HREF\\s*=\\s*(?:\"|')?([^\"'<>]*)(?:\"|')?[^>]*?>\\s*([\\s\\S]*?)\\s*<\\/A>", RegexOptions.IgnoreCase))
			{
				Uri uri = null;
				try
				{
					uri = new Uri(m.Groups[1].Value, UriKind.RelativeOrAbsolute);
				}
				catch { continue; }


				string screentip = m.Groups[2].Value;
				screentip = Regex.Replace(screentip, "【|】|\\[|\\]|\\(|\\)|（|）|<|>|\\s", "");
				if (Regex.IsMatch(screentip, "^第?\\d+页?$"))
				{
					Uri nextpageuri = null;
					if (uri.IsAbsoluteUri)
					{
						if (getUrlPath(currentUrl) == getUrlPath(uri))
							nextpageuri = uri;
						else
							nextpageuri = null;
					}
					else
					{
						if (uri.OriginalString.IndexOf("?") == 0)
						{
							nextpageuri = new Uri(currentUrl.OriginalString.Replace(currentUrl.Query, "") + uri.OriginalString);
						}
						else
						{
							nextpageuri = new Uri(currentUrl, uri);
							if (getUrlPath(currentUrl) != getUrlPath(nextpageuri))
								nextpageuri = null;
						}
					}

					if (nextpageuri != null && nextpageuri.OriginalString.ToLower() != currentUrl.OriginalString.ToLower())
					{
						string pageNoStr = Regex.Match(screentip, @"\d+").Value;
						int pageNo = int.Parse(pageNoStr);
						rtn[pageNo] = nextpageuri.OriginalString;
					}

				}
			}
			return rtn;
		}

		private string getUrlPath(Uri uri)
		{
			if (uri == null)
				return null;
			string url = uri.OriginalString;
			int index = url.LastIndexOf("/");
			if (index > 0)
				return url.Substring(0, index);
			else
				return url;

		}
		#region 鼠标控制

		/// <summary>
		/// 鼠标键按下
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
		{

			if (Makeselection)
			{

				try
				{
					if (e.Button == System.Windows.Forms.MouseButtons.Left && e.Clicks == 1)
					{
						_doubleClick = false;
						_mouseDownPosition = e.Location;
						_scrollTimer.Start();

						if (this.pictureBox1.Cursor == Cursors.Cross)
							startSelection(e);
						else if (this.pictureBox1.Cursor == Cursors.SizeAll)
							startMoveSelection(e);
						else if (this.pictureBox1.Cursor == Cursors.SizeNS || this.pictureBox1.Cursor == Cursors.SizeWE)
							startMoveSelectionEdge(e);
						//pictureBox1.Image = this._oriImage;
					}
					else if (e.Button == System.Windows.Forms.MouseButtons.Left && e.Clicks == 2)
					{
						_doubleClick = true;
						if (this.pictureBox1.Cursor == Cursors.SizeAll)
						{
							//if (this.flowLayoutPanel_MultiPageLinks.Controls.Count == 0)
							//    btn_Done_Click(null, null);
							//else
							btn_Save_Click(null, null);
						}

					}

				}
				catch (Exception ex)
				{
				}
			}



		}

		/// <summary>
		/// 鼠标键抬起
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
		{

			_scrollTimer.Stop();
			if (_doubleClick)
				return;
			if (Math.Abs(e.X - this._mouseDownPosition.X) < 1 && Math.Abs(e.Y - this._mouseDownPosition.Y) < 1)
				return;
			if (Makeselection)
			{

				if (cropPen != null && _currentSelectionArea.cropWidth_Screen > 0 && _currentSelectionArea.cropHeight_Screen > 0)
				{
					if (MoveSelection)
					{

						int offsetX = e.X - moveStartX;
						int offsetY = e.Y - moveStartY;
						_currentSelectionArea.cropX_Screen = _currentSelectionArea.cropX_Screen + offsetX;
						_currentSelectionArea.cropY_Screen = _currentSelectionArea.cropY_Screen + offsetY;
					}
					if (MoveSelectionEdge)
					{

						int offsetX = e.X - moveStartX;
						int offsetY = e.Y - moveStartY;

						switch (draggingEdge)
						{
							case Edge.Left:
								_currentSelectionArea.cropX_Screen = _currentSelectionArea.cropX_Screen + offsetX;
								_currentSelectionArea.cropWidth_Screen = _currentSelectionArea.cropWidth_Screen - offsetX;
								break;
							case Edge.Right:
								_currentSelectionArea.cropWidth_Screen = _currentSelectionArea.cropWidth_Screen + offsetX;
								break;
							case Edge.Top:
								_currentSelectionArea.cropY_Screen = _currentSelectionArea.cropY_Screen + offsetY;
								_currentSelectionArea.cropHeight_Screen = _currentSelectionArea.cropHeight_Screen - offsetY;
								break;
							case Edge.Bottom:
								_currentSelectionArea.cropHeight_Screen = _currentSelectionArea.cropHeight_Screen + offsetY;
								break;
						}

					}

					var currentRatio = getCurrentRatio();
					_currentSelectionArea.cropWidth_Image = (int)(_currentSelectionArea.cropWidth_Screen / currentRatio);
					_currentSelectionArea.cropHeight_Image = (int)(_currentSelectionArea.cropHeight_Screen / currentRatio);
					_currentSelectionArea.cropX_Image = (int)(_currentSelectionArea.cropX_Screen / currentRatio);
					_currentSelectionArea.cropY_Image = (int)(_currentSelectionArea.cropY_Screen / currentRatio);
					Bitmap picWithRectSelection = generatePicWithRectSelection();

					pictureBox1.Image = picWithRectSelection;

				}
			}
			MoveSelection = false;
			MoveSelectionEdge = false;
		}

		private Bitmap generatePicWithRectSelection()
		{
			Bitmap picWithRectSelectiong = new Bitmap(this._oriImage);
			Graphics g = Graphics.FromImage(picWithRectSelectiong);
			int drawWidth = _currentSelectionArea.cropWidth_Image - 1;
			int drawHeight = _currentSelectionArea.cropHeight_Image - 1;
			if (drawWidth > 0 && drawHeight > 0)
			{
				g.DrawRectangle(cropPen, _currentSelectionArea.cropX_Image, _currentSelectionArea.cropY_Image, drawWidth, drawHeight);
				SolidBrush b = new SolidBrush(Color.FromArgb(100, 200, 200, 200));
				g.FillRectangle(b, _currentSelectionArea.cropX_Image, _currentSelectionArea.cropY_Image, drawWidth, drawHeight);
			}
			return picWithRectSelectiong;
		}

		/// <summary>
		/// 鼠标移动
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
		{
			if (Makeselection)
			{
				try
				{
					if (pictureBox1.Image == null)
						return;
					if (e.Button == System.Windows.Forms.MouseButtons.Left)//鼠标左键按下时
					{
						pictureBox1.Image = this._oriImage;
						if (MoveSelection)
						{
							moveSelection(e);
						}
						else if (MoveSelectionEdge)
						{
							moveSelectionEdge(e);
						}
						else
							select(e);
					}
					else
					{

						if (_currentSelectionArea.cropHeight_Screen > 0 && _currentSelectionArea.cropWidth_Screen > 0)
						{
							int margin = 4;

							if (e.X > _currentSelectionArea.cropX_Screen - margin && e.X < _currentSelectionArea.cropX_Screen + margin
								&& e.Y > _currentSelectionArea.cropY_Screen + margin && e.Y < _currentSelectionArea.cropY_Screen + _currentSelectionArea.cropHeight_Screen - margin)
							{
								this.draggingEdge = Edge.Left;
								this.CurrentMouseAction = MouseAction.MoveSelectionEdge;
							}
							else if (e.X > _currentSelectionArea.cropX_Screen + _currentSelectionArea.cropWidth_Screen - margin && e.X < _currentSelectionArea.cropX_Screen + _currentSelectionArea.cropWidth_Screen + margin
								&& e.Y > _currentSelectionArea.cropY_Screen + margin && e.Y < _currentSelectionArea.cropY_Screen + _currentSelectionArea.cropHeight_Screen - margin)
							{

								this.draggingEdge = Edge.Right;
								this.CurrentMouseAction = MouseAction.MoveSelectionEdge;
							}
							else if (e.Y > _currentSelectionArea.cropY_Screen - margin && e.Y < _currentSelectionArea.cropY_Screen + margin
								&& e.X > _currentSelectionArea.cropX_Screen + margin && e.X < _currentSelectionArea.cropX_Screen + _currentSelectionArea.cropWidth_Screen - margin)
							{
								this.draggingEdge = Edge.Top;
								this.CurrentMouseAction = MouseAction.MoveSelectionEdge;
							}
							else if (e.Y > _currentSelectionArea.cropY_Screen + _currentSelectionArea.cropHeight_Screen - margin && e.Y < _currentSelectionArea.cropY_Screen + _currentSelectionArea.cropHeight_Screen + margin
								 && e.X > _currentSelectionArea.cropX_Screen + margin && e.X < _currentSelectionArea.cropX_Screen + _currentSelectionArea.cropWidth_Screen - margin)
							{
								this.draggingEdge = Edge.Bottom;
								this.CurrentMouseAction = MouseAction.MoveSelectionEdge;
							}

							else if (e.X > _currentSelectionArea.cropX_Screen && e.X < _currentSelectionArea.cropX_Screen + _currentSelectionArea.cropWidth_Screen
								&& e.Y > _currentSelectionArea.cropY_Screen && e.Y < _currentSelectionArea.cropY_Screen + _currentSelectionArea.cropHeight_Screen)
							{
								this.CurrentMouseAction = MouseAction.MoveSelection;
							}
							else
							{
								this.CurrentMouseAction = MouseAction.Selection;
							}
						}
						else
						{
							this.CurrentMouseAction = MouseAction.Selection;
						}

					}



				}
				catch (Exception ex)
				{

				}
			}


		}


		private void startMoveSelectionEdge(MouseEventArgs e)
		{
			MoveSelectionEdge = true;
			moveStartX = e.X;
			moveStartY = e.Y;
		}
		private void moveSelectionEdge(MouseEventArgs e)
		{
			this._currentMousePosition = e.Location;
			int offsetX = e.X - moveStartX;
			int offsetY = e.Y - moveStartY;
			int newX = _currentSelectionArea.cropX_Screen;
			int newY = _currentSelectionArea.cropY_Screen;
			int newWidth = _currentSelectionArea.cropWidth_Screen;
			int newHeight = _currentSelectionArea.cropHeight_Screen;
			switch (draggingEdge)
			{
				case Edge.Left:
					newX = _currentSelectionArea.cropX_Screen + offsetX;
					newWidth = _currentSelectionArea.cropWidth_Screen - offsetX;
					break;
				case Edge.Right:
					newWidth = _currentSelectionArea.cropWidth_Screen + offsetX;
					break;
				case Edge.Top:
					newY = _currentSelectionArea.cropY_Screen + offsetY;
					newHeight = _currentSelectionArea.cropHeight_Screen - offsetY;
					break;
				case Edge.Bottom:
					newHeight = _currentSelectionArea.cropHeight_Screen + offsetY;
					break;
			}
			if (newHeight == _currentSelectionArea.cropHeight_Screen && newWidth == _currentSelectionArea.cropWidth_Screen)
				return;
			pictureBox1.Refresh();
			pictureBox1.CreateGraphics().DrawRectangle(cropPen, newX, newY, newWidth, newHeight);
			SolidBrush b = new SolidBrush(Color.FromArgb(100, 200, 200, 200));
			pictureBox1.CreateGraphics().FillRectangle(b, newX, newY, newWidth, newHeight);
			setSelectionSizeLabel(newWidth, newHeight);
		}



		private void startSelection(MouseEventArgs e)
		{
			_currentSelectionArea.cropX_Screen = e.X;
			_currentSelectionArea.cropY_Screen = e.Y;
			_currentSelectionArea.cropHeight_Screen = 0;
			_currentSelectionArea.cropWidth_Screen = 0;


			setSelectionSizeLabel(0, 0);
		}

		private void select(MouseEventArgs e)
		{
			pictureBox1.Refresh();
			int x = Math.Min(e.X, pictureBox1.Width);
			int y = Math.Min(e.Y, pictureBox1.Height);
			_currentSelectionArea.cropWidth_Screen = x - _currentSelectionArea.cropX_Screen;
			_currentSelectionArea.cropHeight_Screen = y - _currentSelectionArea.cropY_Screen;
			int drawWidth = _currentSelectionArea.cropWidth_Screen - 1;
			int drawHeight = _currentSelectionArea.cropHeight_Screen - 1;
			if (drawHeight > 0 && drawWidth > 0)
			{
				pictureBox1.CreateGraphics().DrawRectangle(cropPen, _currentSelectionArea.cropX_Screen, _currentSelectionArea.cropY_Screen, _currentSelectionArea.cropWidth_Screen, _currentSelectionArea.cropHeight_Screen);
				SolidBrush b = new SolidBrush(Color.FromArgb(100, 200, 200, 200));
				pictureBox1.CreateGraphics().FillRectangle(b, _currentSelectionArea.cropX_Screen, _currentSelectionArea.cropY_Screen, drawWidth, drawHeight);
			}
			_currentMousePosition = e.Location;

			setSelectionSizeLabel(_currentSelectionArea.cropWidth_Screen, _currentSelectionArea.cropHeight_Screen);
		}



		private void startMoveSelection(MouseEventArgs e)
		{
			MoveSelection = true;
			moveStartX = e.X;
			moveStartY = e.Y;
		}
		private void moveSelection(MouseEventArgs e)
		{
			this._currentMousePosition = e.Location;
			int offsetX = e.X - moveStartX;
			int offsetY = e.Y - moveStartY;
			if (offsetX == 0 || offsetY == 0)
				return;

			pictureBox1.Refresh();
			pictureBox1.CreateGraphics().DrawRectangle(cropPen, _currentSelectionArea.cropX_Screen + offsetX, _currentSelectionArea.cropY_Screen + offsetY, _currentSelectionArea.cropWidth_Screen, _currentSelectionArea.cropHeight_Screen);
			SolidBrush b = new SolidBrush(Color.FromArgb(100, 200, 200, 200));
			pictureBox1.CreateGraphics().FillRectangle(b, _currentSelectionArea.cropX_Screen + offsetX, _currentSelectionArea.cropY_Screen + offsetY, _currentSelectionArea.cropWidth_Screen, _currentSelectionArea.cropHeight_Screen);
		}

		private MouseAction _currentMouseAction = MouseAction.Selection;
		public MouseAction CurrentMouseAction
		{
			get
			{
				return _currentMouseAction;
			}
			set
			{
				_currentMouseAction = value;
				if (value == MouseAction.Selection)
				{
					if (this.isbusy == false)
						pictureBox1.Cursor = Cursors.Cross;
					else
						pictureBox1.Cursor = Cursors.WaitCursor;
				}
				else if (value == MouseAction.MoveSelection)
				{
					pictureBox1.Cursor = Cursors.SizeAll;
				}
				else
				{
					if (this.draggingEdge == Edge.Top || this.draggingEdge == Edge.Bottom)
					{
						this.pictureBox1.Cursor = Cursors.SizeNS;
					}
					else
					{
						this.pictureBox1.Cursor = Cursors.SizeWE;
					}

				}

			}

		}
		#endregion

		/// <summary>
		/// 更新图片大小的显示
		/// </summary>
		private void setImgSizeLabel()
		{
			this.label_ImageSize.Text = string.Format("图片大小：{0}×{1}像素", this._oriImage.Width, this._oriImage.Height);


		}
		/// <summary>
		/// 更新当前选中区域大小的显示
		/// </summary>
		/// <param name="cropWidth"></param>
		/// <param name="cropHeight"></param>
		private void setSelectionSizeLabel(int cropWidth, int cropHeight)
		{

			var currentRatio = getCurrentRatio();
			int realWidth = (int)(cropWidth / currentRatio);
			int realHeight = (int)(cropHeight / currentRatio);
			if (cropWidth > 0 && cropHeight > 0)
			{
				this.label_SelectionSize.Text = string.Format("选中大小：{0}×{1}像素", realWidth, realHeight);
			}
			else
				this.label_SelectionSize.Text = null;
		}

		/// <summary>
		/// 保存为文件
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_SaveAs_Click(object sender, EventArgs e)
		{
			if (this._oriImage == null)
				return;

			SaveFileDialog dlg = new SaveFileDialog();
			//设置文件类型  
			dlg.Filter = "PNG(*.png)|*.png|JPEG(*.jpg;*.jpeg)|*.jpg;*.jpeg|GIF(*.gif)|*.gif|BMP(*.bmp)|*.bmp";

			//设置默认文件类型显示顺序  
			dlg.FilterIndex = 2;

			var result = dlg.ShowDialog();
			if (result == System.Windows.Forms.DialogResult.OK)
			{
				try
				{
					ImageFormat format = ImageFormat.Jpeg;
					switch (dlg.FilterIndex)
					{
						case 1:
							format = ImageFormat.Png;
							break;
						case 2:
							format = ImageFormat.Jpeg;
							break;
						case 3:
							format = ImageFormat.Gif;
							break;
						case 4:
							format = ImageFormat.Bmp;
							break;

					}
					_oriImage.Save(dlg.FileName, format);
					MessageBox.Show("保存完成。");
				}
				catch (Exception ex)
				{
					MessageBox.Show("保存失败:" + ex.Message);
				}
			}
		}


		/// <summary>
		/// 切换缩放比例 原始大小/自适应
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_ImgSize_Click(object sender, EventArgs e)
		{
			if (this.pictureBox1.Image == null)
				return;


			if (btn_ImgSize.Text == oriStr)//设为原始大小
			{
				changeToOriSize();
			}
			else//设为自适应 
			{
				changeToAutoSize();
			}
		}

		/// <summary>
		/// 将缩放比例设为自动适应控件大小
		/// </summary>
		private void changeToAutoSize()
		{
			btn_ImgSize.Text = oriStr;
			this.pictureBox1.Dock = DockStyle.Fill;
			this.pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;

			var ratio = getCurrentRatio();
			this.pictureBox1.Dock = DockStyle.None;
			this.pictureBox1.Width = (int)(_oriImage.Width * ratio);
			this.pictureBox1.Height = (int)(_oriImage.Height * ratio);
			this.pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
			this.pictureBox1.Location = new Point(0, 0);
			_currentSelectionArea.cropX_Screen = (int)(_currentSelectionArea.cropX_Image * ratio);
			_currentSelectionArea.cropY_Screen = (int)(_currentSelectionArea.cropY_Image * ratio);
			_currentSelectionArea.cropWidth_Screen = (int)(_currentSelectionArea.cropWidth_Image * ratio);
			_currentSelectionArea.cropHeight_Screen = (int)(_currentSelectionArea.cropHeight_Image * ratio);

			setRatioLabel();
			setRatioTrackBar();
		}

		/// <summary>
		///将缩放比例调为原始大小
		/// </summary>
		private void changeToOriSize()
		{
			btn_ImgSize.Text = autoStr;
			this.pictureBox1.Dock = DockStyle.None;
			this.pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
			this.trackBar1.Value = 3;
			int ratio = 1;
			this.label_Ratio.Text = ratio.ToString("P2");

			_currentSelectionArea.cropX_Screen = (int)(_currentSelectionArea.cropX_Image * ratio);
			_currentSelectionArea.cropY_Screen = (int)(_currentSelectionArea.cropY_Image * ratio);
			_currentSelectionArea.cropWidth_Screen = (int)(_currentSelectionArea.cropWidth_Image * ratio);
			_currentSelectionArea.cropHeight_Screen = (int)(_currentSelectionArea.cropHeight_Image * ratio);
		}

		private void trackBar1_ValueChanged(object sender, EventArgs e)
		{
			if (this._oriImage == null)
				return;
			this.splitContainer1.Panel1.AutoScrollPosition = new Point(0, 0);
			double ratio = _ratios[trackBar1.Value];
			this.pictureBox1.Dock = DockStyle.None;
			this.pictureBox1.Width = (int)(_oriImage.Width * ratio);
			this.pictureBox1.Height = (int)(_oriImage.Height * ratio);
			this.pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
			this.label_Ratio.Text = ratio.ToString("P2");
			_currentSelectionArea.cropX_Screen = (int)(_currentSelectionArea.cropX_Image * ratio);
			_currentSelectionArea.cropY_Screen = (int)(_currentSelectionArea.cropY_Image * ratio);
			_currentSelectionArea.cropWidth_Screen = (int)(_currentSelectionArea.cropWidth_Image * ratio);
			_currentSelectionArea.cropHeight_Screen = (int)(_currentSelectionArea.cropHeight_Image * ratio);
		}

		private void setRatioTrackBar()
		{
			double ratio = getCurrentRatio();
			if (ratio < _ratios[0])
				this.trackBar1.Value = 0;
			else if (ratio > _ratios[6])
				this.trackBar1.Value = 6;
			else
			{
				for (int i = 0; i < 6; i++)
				{
					if (ratio >= _ratios[i] && ratio <= _ratios[i + 1])
					{
						if (_ratios[i + 1] - ratio >= ratio - _ratios[i])
						{
							this.trackBar1.Value = i + 1;
						}
						else
						{
							this.trackBar1.Value = i;
						}
						break;
					}
				}

			}
		}

		/// <summary>
		/// 更新当前缩放比例的显示
		/// </summary>
		private void setRatioLabel()
		{
			if (this._oriImage == null)
				return;
			double ratio = getCurrentRatio();
			this.label_Ratio.Text = ratio.ToString("P2");

		}

		/// <summary>
		/// 获取当前缩放比例
		/// </summary>
		/// <returns></returns>
		private double getCurrentRatio()
		{
			if (this._oriImage == null)
				return 1;
			int imgHeight = this._oriImage.Height;
			int imgWidth = this._oriImage.Width;
			int picBoxHeight = this.pictureBox1.Height;
			int picBoxWidth = this.pictureBox1.Width;


			double heightRatio = (double)picBoxHeight / (double)imgHeight;
			double widthRatio = (double)picBoxWidth / (double)imgWidth;

			double ratio = Math.Min(heightRatio, widthRatio);
			return ratio;
		}

		/// <summary>
		/// 缩放比例减小一级
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_Zoomout_Click(object sender, EventArgs e)
		{
			if (trackBar1.Value > trackBar1.Minimum)
			{
				trackBar1.Value -= 1;
				trackBar1_ValueChanged(null, null);
			}
		}

		/// <summary>
		/// 缩放比例增大一级
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_Zoomin_Click(object sender, EventArgs e)
		{
			if (trackBar1.Value < trackBar1.Maximum)
			{
				trackBar1.Value += 1;
				trackBar1_ValueChanged(null, null);
			}
		}





		/// <summary>
		/// 自动调整地址栏长度
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void toolStrip1_Resize(object sender, EventArgs e)
		{
			var width = toolStrip1.Width;
			width = Math.Max(200, width - 150);
			txt_URL.Size = new Size(width, txt_URL.Height);
			toolStrip1.Refresh();
		}


		/// <summary>
		/// 【选择】按钮选中状态变化时
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_Select_CheckStateChanged(object sender, EventArgs e)
		{
			if (btn_Select.Checked)
			{
				this.Makeselection = true;
				pictureBox1.Cursor = Cursors.Cross;
			}
			else
			{
				this.Makeselection = false;
				this.pictureBox1.Image = this._oriImage;
				pictureBox1.Cursor = Cursors.Default;
				clearSelectionInfo();
			}
		}

		private void clearSelectionInfo()
		{
			_currentSelectionArea.Clear();
			setSelectionSizeLabel(0, 0);
		}

		/// <summary>
		/// 复制
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_Copy_Click(object sender, EventArgs e)
		{
			insertToClipboard();
		}

		/// <summary>
		/// 剪切
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_Cut_Click(object sender, EventArgs e)
		{

			insertToClipboard();
			btn_Del_Click(null, null);
		}
		/// <summary>
		/// 删除选定区域
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_Del_Click(object sender, EventArgs e)
		{
			if (_currentSelectionArea.cropWidth_Screen > 0 && _currentSelectionArea.cropHeight_Screen > 0)
			{
				this._undoImage = this._oriImage;
				var selectedRect = new Rectangle(_currentSelectionArea.cropX_Image, _currentSelectionArea.cropY_Image, _currentSelectionArea.cropWidth_Image, _currentSelectionArea.cropHeight_Image);
				Bitmap newImg = new Bitmap(this._oriImage);
				Graphics og = Graphics.FromImage(newImg);
				og.FillRectangle(Brushes.White, selectedRect);
				this._oriImage = newImg;
				pictureBox1.Image = this._oriImage;
				clearSelectionInfo();
			}
		}
		/// <summary>
		/// 撤销
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_Undo_Click(object sender, EventArgs e)
		{
			if (this._undoImage != null)
			{
				this._oriImage = this._undoImage;
				this.pictureBox1.Image = this._undoImage;
			}
		}

		/// <summary>
		/// 复制到剪切板
		/// </summary>
		private void insertToClipboard()
		{
			if (this._oriImage == null)
				return;
			Bitmap imgToCopy = null;
			if (_currentSelectionArea.cropWidth_Screen > 0 && _currentSelectionArea.cropHeight_Screen > 0)
			{
				Rectangle selectedRect;
				imgToCopy = getSelectedAreaBitmap(out selectedRect);
			}
			else
			{
				imgToCopy = this._oriImage;

			}
			Clipboard.SetImage(imgToCopy);
		}
		/// <summary>
		/// 将图片插入剪报列表中
		/// </summary>
		private void insertImgToClipping()
		{
			if (this._oriImage == null)
				return;
			Bitmap imgToCopy = null;
			if (_currentSelectionArea.cropWidth_Screen > 0 && _currentSelectionArea.cropHeight_Screen > 0)
			{
				Rectangle selectedRect;
				imgToCopy = getSelectedAreaBitmap(out selectedRect);
			}
			else
			{
				imgToCopy = this._oriImage;

			}

			this._addPic.Invoke(imgToCopy);
		}

		/// <summary>
		/// 获取选中区域的Bitmap
		/// </summary>
		/// <param name="selectedRect"></param>
		/// <returns></returns>
		private Bitmap getSelectedAreaBitmap(out Rectangle selectedRect)
		{
			selectedRect = new Rectangle(_currentSelectionArea.cropX_Image, _currentSelectionArea.cropY_Image, _currentSelectionArea.cropWidth_Image, _currentSelectionArea.cropHeight_Image);

			Bitmap imgToCopy = new Bitmap(_currentSelectionArea.cropWidth_Image, _currentSelectionArea.cropHeight_Image);
			// for cropinf image
			Graphics g = Graphics.FromImage(imgToCopy);
			// create graphics
			g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
			g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
			g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
			//set image attributes
			g.DrawImage(this._oriImage, 0, 0, selectedRect, GraphicsUnit.Pixel);
			return imgToCopy;
		}


		/// <summary>
		/// 剪裁
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_Crop_Click(object sender, EventArgs e)
		{
			if (this._oriImage == null)
				return;
			if (_currentSelectionArea.cropWidth_Screen > 0 && _currentSelectionArea.cropHeight_Screen > 0)
			{
				this._undoImage = this._oriImage;
				Rectangle selectedRect;
				var imgToCopy = getSelectedAreaBitmap(out selectedRect);
				clearSelectionInfo();
				this._oriImage = imgToCopy;
				this.pictureBox1.Image = this._oriImage;
				changeToOriSize();
				setImgSizeLabel();

			}

		}

		private void btn_Save_Click(object sender, EventArgs e)
		{


			insertImgToClipping();
			this.toolStripLabel_Info.Text = "保存成功...";
			_infoShowCount = 0;
			_infoTimer.Start();

		}



		/// <summary>
		/// 完成
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btn_Done_Click(object sender, EventArgs e)
		{
			insertImgToClipping();
			this.Close();
		}


		public enum MouseAction
		{
			Selection,
			MoveSelection,
			MoveSelectionEdge
		}
		public enum Edge
		{
			Left,
			Right,
			Top,
			Bottom
		}
		public class SelectionInfo
		{
			public int cropX_Screen;
			public int cropY_Screen;
			public int cropWidth_Screen;
			public int cropHeight_Screen;
			public int cropX_Image;
			public int cropY_Image;
			public int cropWidth_Image;
			public int cropHeight_Image;

			public void Clear()
			{
				this.cropHeight_Image = 0;
				this.cropHeight_Screen = 0;
				this.cropWidth_Image = 0;
				this.cropWidth_Screen = 0;
				this.cropX_Image = 0;
				this.cropX_Screen = 0;
				this.cropY_Image = 0;
				this.cropY_Screen = 0;
			}
		}

		private void btn_SelectAll_Click(object sender, EventArgs e)
		{
			if (this._oriImage == null)
				return;
			this._currentSelectionArea.cropX_Image = 0;
			this._currentSelectionArea.cropX_Screen = 0;
			this._currentSelectionArea.cropY_Image = 0;
			this._currentSelectionArea.cropY_Screen = 0;
			this._currentSelectionArea.cropHeight_Image = this._oriImage.Height;
			this._currentSelectionArea.cropWidth_Image = this._oriImage.Width;
			this._currentSelectionArea.cropHeight_Screen = this.pictureBox1.Height;
			this._currentSelectionArea.cropWidth_Screen = this.pictureBox1.Width;
			Bitmap picWithRectSelection = generatePicWithRectSelection();

			pictureBox1.Image = picWithRectSelection;
			setSelectionSizeLabel(this._oriImage.Width, this._oriImage.Height);
		}

		private void btn_SelectPageUp_Click(object sender, EventArgs e)
		{
			if (_currentSelectionArea.cropHeight_Image >= _oriImage.Height)
				return;
			selectionMoveUp(_currentSelectionArea.cropHeight_Image);
			scrollToSelectionStart();
		}

		private void btn_SelectPageDown_Click(object sender, EventArgs e)
		{
			if (_currentSelectionArea.cropHeight_Image >= _oriImage.Height)
				return;
			selectionMoveDown(_currentSelectionArea.cropHeight_Image);
			scrollToSelectionStart();
		}

		private void scrollToSelectionStart()
		{
			int margin = Math.Min(this.pictureBox1.Height / 3, 30);
			this.splitContainer1.Panel1.AutoScrollPosition = new Point(0, Math.Max(_currentSelectionArea.cropY_Screen - margin, 0));

		}

		private void selectionMoveUp(int step)
		{
			_currentSelectionArea.cropY_Image = _currentSelectionArea.cropY_Image - step;
			if (_currentSelectionArea.cropY_Image + _currentSelectionArea.cropHeight_Image < 0)
				_currentSelectionArea.cropY_Image = 0 - _currentSelectionArea.cropHeight_Image;
			setScreenSelectionInfo();
			this.pictureBox1.Image = generatePicWithRectSelection();
		}
		private void selectionMoveDown(int step)
		{
			if (_currentSelectionArea.cropHeight_Image < 1
					|| _currentSelectionArea.cropWidth_Image < 1)
				return;
			_currentSelectionArea.cropY_Image = _currentSelectionArea.cropY_Image + step;
			if (_currentSelectionArea.cropY_Image > _oriImage.Height)
				_currentSelectionArea.cropY_Image = _oriImage.Height;
			setScreenSelectionInfo();
			this.pictureBox1.Image = generatePicWithRectSelection();
		}
		private void selectionMoveLeft(int step)
		{
			if (_currentSelectionArea.cropHeight_Image < 1
				|| _currentSelectionArea.cropWidth_Image < 1)
				return;
			_currentSelectionArea.cropX_Image = _currentSelectionArea.cropX_Image - step;
			if (_currentSelectionArea.cropX_Image + _currentSelectionArea.cropWidth_Image < 0)
				_currentSelectionArea.cropX_Image = 0 - _currentSelectionArea.cropWidth_Image;
			setScreenSelectionInfo();
			this.pictureBox1.Image = generatePicWithRectSelection();
		}
		private void selectionMoveRight(int step)
		{
			if (_currentSelectionArea.cropHeight_Image < 1
				|| _currentSelectionArea.cropWidth_Image < 1)
				return;
			_currentSelectionArea.cropX_Image = _currentSelectionArea.cropX_Image + step;
			if (_currentSelectionArea.cropX_Image > _oriImage.Width)
				_currentSelectionArea.cropX_Image = _oriImage.Width;
			setScreenSelectionInfo();
			this.pictureBox1.Image = generatePicWithRectSelection();
		}
		private void setScreenSelectionInfo()
		{
			var ratio = getCurrentRatio();
			_currentSelectionArea.cropHeight_Screen = (int)(_currentSelectionArea.cropHeight_Image * ratio);
			_currentSelectionArea.cropWidth_Screen = (int)(_currentSelectionArea.cropWidth_Image * ratio);
			_currentSelectionArea.cropX_Screen = (int)(_currentSelectionArea.cropX_Image * ratio);
			_currentSelectionArea.cropY_Screen = (int)(_currentSelectionArea.cropY_Image * ratio);
		}

		private void toolStripMenuItem_MoveUp_Click(object sender, EventArgs e)
		{
			selectionMoveUp(1);
		}

		private void toolStripMenuItem_Down_Click(object sender, EventArgs e)
		{
			selectionMoveDown(1);
		}

		private void toolStripMenuItem_MoveLeft_Click(object sender, EventArgs e)
		{
			selectionMoveLeft(1);
		}

		private void toolStripMenuItem_MoveRight_Click(object sender, EventArgs e)
		{
			selectionMoveRight(1);
		}
	}
}
